grammar Bst;

options {
    output=AST;
}

tokens {
	IDLIST;
	STACK;
	ENTRY;
	COMMANDS;
}

program : commands+ -> ^(COMMANDS commands+);

commands 
	: STRINGS^^ idList
	| INTEGERS^^ idList
	| FUNCTION^^ id stack
	| MACRO^^ id '{'! STRING '}'!
	| READ^^
	| EXECUTE^^ '{'! function '}'!
	| ITERATE^^ '{'! function '}'!
	| REVERSE^^ '{'! function '}'!
	| ENTRY^^ idList0 idList0 idList0
	| SORT^^;

identifier 
	: IDENTIFIER;

id 
	: '{'! identifier '}'!;
	
idList 
	: '{' identifier+ '}' -> ^(IDLIST identifier+);
	
idList0 
	: '{' identifier* '}' -> ^(IDLIST identifier*);

function 
	: '<' | '>' | '=' | '+' | '-' | ':=' | '*' | identifier;
	
stack 
	: '{' stackitem+ '}' -> ^(STACK stackitem+);
	
stackitem
	: function
	| STRING 
	| INTEGER 
	| QUOTED
	| stack;

STRINGS : 'STRINGS';
INTEGERS : 'INTEGERS';
FUNCTION : 'FUNCTION';
EXECUTE : 'EXECUTE';
SORT : 'SORT';
ITERATE : 'ITERATE';
REVERSE : 'REVERSE';
ENTRY : 'ENTRY';
READ : 'READ';
MACRO : 'MACRO';

QUOTED
	: '\'' IDENTIFIER;

IDENTIFIER
	: LETTER (LETTER|NUMERAL)* ;

fragment LETTER
	: ('a'..'z'|'A'..'Z'|'.'|'$');

STRING
	: '"' (~('"'))* '"';
	
INTEGER   
	: '#' ('+'|'-')? NUMERAL+ ;

fragment NUMERAL
	: ('0'..'9');
	
WS
	: (' '|'\t'|'\n')+ {channel=99;} ;
	
LINE_COMMENT
    : '%' ~('\n'|'\r')* '\r'? '\n' {channel=99;}
    ;
	